package com.sunseen.capacitormachine.commumication.tcp;

import android.util.Log;
import android.util.SparseIntArray;

import com.sunseen.capacitormachine.common.event.ConnectStateChangeEvent;
import com.sunseen.capacitormachine.commumication.mqtt.bean.DetectionResult;
import com.sunseen.capacitormachine.commumication.mqtt.bean.IVBatchJsonObj;
import com.sunseen.capacitormachine.commumication.mqtt.bean.IVData;
import com.sunseen.capacitormachine.commumication.mqtt.bean.OvenTemperatureBatchData;
import com.sunseen.capacitormachine.commumication.mqtt.bean.OvenTemperatureBatchJsonObj;
import com.sunseen.capacitormachine.commumication.mqtt.bean.ResultData;
import com.sunseen.capacitormachine.commumication.mqtt.event.SendJsonObjEvent;
import com.sunseen.capacitormachine.commumication.tcp.event.DetectedImplosionEvent;
import com.sunseen.capacitormachine.commumication.tcp.event.HolderTemperatureEvent;
import com.sunseen.capacitormachine.commumication.tcp.event.PortOffLineEvent;
import com.sunseen.capacitormachine.data.Constant;
import com.sunseen.capacitormachine.data.ObjectBox;
import com.sunseen.capacitormachine.common.MethodUtil;
import com.sunseen.capacitormachine.commumication.tcp.event.NodeOffLineEvent;
import com.sunseen.capacitormachine.commumication.tcp.event.ViEvent;
import com.sunseen.capacitormachine.data.DataUtil;
import com.sunseen.capacitormachine.data.bean.CapacitorBean;
import com.sunseen.capacitormachine.data.bean.HolderBean;

import org.greenrobot.eventbus.EventBus;

import java.util.ArrayList;
import java.util.List;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.objectbox.Box;

public class ParseHandler extends SimpleChannelInboundHandler<ByteBuf> {

    private String TAG;
    private int portId;

    private Box<CapacitorBean> capacitorBeanBox;

    private List<UVIBean> uviBeanList = new ArrayList<>();

    public void init(int portId) {
        TAG = ParseHandler.class.getSimpleName() + portId;
        this.portId = portId;
        capacitorBeanBox = ObjectBox.getBoxStore().boxFor(CapacitorBean.class);
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
        Log.e(TAG, "channelActive");
        EventBus.getDefault().post(new ConnectStateChangeEvent(portId, false));
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        super.channelInactive(ctx);
        Log.e(TAG, "channelInactive");
        EventBus.getDefault().post(new ConnectStateChangeEvent(portId, true));
    }

    private boolean holderOffLineClean = true;

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf byteBuf) throws Exception {
//        if (BuildConfig.DEBUG) {
//            //从功能码开始将此帧数据打Log
//            byte[] bytes = new byte[12];
//            byteBuf.getBytes(1, bytes);
//            String hexStr = getHexDatas(bytes).toString();
//            Log.e(TAG, hexStr);
//        }
        byteBuf.skipBytes(1);//去掉0x88帧头
        short type = byteBuf.readUnsignedByte();//读取功能码
        if (type <= 0x19) {//数据功能码
            final int index = Constant.HolderPosTable[portId][byteBuf.readUnsignedByte()];
            final HolderBean holderBean = DataUtil.holderList.get(index);
            final List<CapacitorBean> capacitorBeanList = holderBean.capacitorList;
            final int pos1 = (type - 0x10) * 2;
            //现默认夹具中有21颗电容(第一颗用占位进出料链条的空位)，有效电容索引值为后20颗电容，故索引值加1
            CapacitorBean capacitorBean1 = capacitorBeanList.get(pos1 + 1);
            final int current1 = byteBuf.readUnsignedShort();
            final int voltage1 = byteBuf.readUnsignedShort();
            if (!capacitorBean1.isEmpty()) {
                uviBeanList.add(new UVIBean(capacitorBean1.getUid(), capacitorBean1.getSequence(), current1, voltage1));
            }
            if (byteBuf.readUnsignedByte() == 1) {//红外上报内爆
                if (!capacitorBean1.isEmpty() && capacitorBean1.isNormal()) {
                    String uid = capacitorBean1.getUid();
                    capacitorBean1.setNormal(false);
                    capacitorBeanBox.put(capacitorBean1);
                    ResultData resultData = new ResultData(uid, 1);
                    int time2 = (int) (System.currentTimeMillis() / 1000);
                    EventBus.getDefault().post(new SendJsonObjEvent(
                            new DetectionResult(DetectionResult.IMPLOSION, time2, resultData)));
                    EventBus.getDefault().post(new DetectedImplosionEvent(holderBean.getHolderId(), pos1));
                }
            }

            final int pos2 = pos1 + 1;
            //现默认夹具中有21颗电容(第一颗用占位进出料链条的空位)，有效电容索引值为后20颗电容，故索引值加1
            final CapacitorBean capacitorBean2 = capacitorBeanList.get(pos2 + 1);
            final int current2 = byteBuf.readUnsignedShort();
            final int voltage2 = byteBuf.readUnsignedShort();
            if (!capacitorBean2.isEmpty()) {
                uviBeanList.add(new UVIBean(capacitorBean2.getUid(), capacitorBean2.getSequence(), current2, voltage2));
            }
            final int holderId = DataUtil.holderList.get(index).getHolderId();
//            Log.e(TAG, "holderId = " + holderId + " curHolderId = " + DataUtil.CurrentHolderId);
//            Log.e(TAG, "CurrentPos = " + DataUtil.CurrentCapacitorPos);
            if (holderId == DataUtil.CurrentHolderId) {
                if (DataUtil.CurrentCapacitorPos == pos1) {
                    EventBus.getDefault().post(new ViEvent(voltage1, current1));
                } else if (DataUtil.CurrentCapacitorPos == pos2) {
                    EventBus.getDefault().post(new ViEvent(voltage2, current2));
                }
            }
            if (byteBuf.readUnsignedByte() == 1) {//红外上报内爆
                if (!capacitorBean2.isEmpty() && capacitorBean2.isNormal()) {
                    String uid = capacitorBean2.getUid();
                    capacitorBean2.setNormal(false);
                    capacitorBeanBox.put(capacitorBean2);
                    ResultData resultData = new ResultData(uid, 1);
                    int time3 = (int) (System.currentTimeMillis() / 1000);
                    EventBus.getDefault().post(new SendJsonObjEvent(
                            new DetectionResult(DetectionResult.IMPLOSION, time3, resultData)));
                    EventBus.getDefault().post(new DetectedImplosionEvent(holderBean.getHolderId(), pos2));
                }
            }
        } else if (type == 0x1F) {//夹具状态功能码
            final short holderBaseIndex = byteBuf.readUnsignedByte();
            int offLineFlag1 = byteBuf.readUnsignedByte();
            int offLineFlag2 = byteBuf.readUnsignedByte();
            int offLineFlag3 = byteBuf.readUnsignedByte();
            boolean hasOff = true;
//            Log.e("xiaochunhui2", portId + "");
            if(portId == 1){
                //01
                //0 0 1
                if(holderBaseIndex == 1 && offLineFlag1 == 0 && offLineFlag2 == 0 && offLineFlag3 == 1){
//                    Log.e("xiaochunhui  ",offLineFlag1 + ", " + offLineFlag2 + ", " + offLineFlag3 + ", " + portId);
                    hasOff = false;
                }
            } else if(portId == 0){
                //02
                //1 0 0
                if(holderBaseIndex == 2 && offLineFlag1 == 1 && offLineFlag2 == 0 && offLineFlag3 == 0){
//                    Log.e("xiaochunhui  ",offLineFlag1 + ", " + offLineFlag2 + ", " + offLineFlag3 + ", " + portId);
                    hasOff = false;
                }
            }
            if ((offLineFlag1 + offLineFlag2 + offLineFlag3) > 0 && hasOff) {//有端口掉线
                //hasOff = true;
                EventBus.getDefault().post(new PortOffLineEvent(portId, holderBaseIndex, offLineFlag1, offLineFlag2, offLineFlag3, true));
            }
            byteBuf.skipBytes(1);
            final int temp1 = byteBuf.readUnsignedShort();
            final int holderIndex1 = getHolderIndex(holderBaseIndex, 1);
            final int holderId1 = setTempThanReturnHolderId(temp1, holderIndex1);

            if (holderId1 > 0) {
                sendTemp(temp1, holderId1);
            }

            final int temp2 = byteBuf.readUnsignedShort();
            final int holderIndex2 = getHolderIndex(holderBaseIndex, 2);
            final int holderId2 = setTempThanReturnHolderId(temp2, holderIndex2);
            if (holderId2 > 0) {
                sendTemp(temp2, holderId2);
            }

            final int temp3 = byteBuf.readUnsignedShort();
            final int holderIndex3 = getHolderIndex(holderBaseIndex, 3);
            final int holderId3 = setTempThanReturnHolderId(temp3, holderIndex3);
            if (holderId3 > 0) {
                sendTemp(temp3, holderId3);
            }
//            Log.e(TAG, "channelRead0: holderId = " + holderId1 + " " + holderId2 + " " + holderId3);
            if (DataUtil.TapHolderId == holderId1) {
                EventBus.getDefault().post(new HolderTemperatureEvent(temp1));
            } else if (DataUtil.TapHolderId == holderId2) {
                EventBus.getDefault().post(new HolderTemperatureEvent(temp2));
            } else if (DataUtil.TapHolderId == holderId3) {
                EventBus.getDefault().post(new HolderTemperatureEvent(temp3));
            }

        } else if (type == 0x1E) {//节点状态功能码
            //检测节点状态，有掉线信号就发出事件
            boolean hasOffLine = false;
            SparseIntArray intArray = new SparseIntArray();
            byte[] frameByte = new byte[byteBuf.readableBytes()];
            byteBuf.readBytes(frameByte);
            for (int i = 1, size = frameByte.length; i < size; i++) {
                if (frameByte[i] != 0) {
                    intArray.append(intArray.size(), i);
                    if (!hasOffLine) {
                        hasOffLine = true;
                    }
                }
            }
            if (hasOffLine) {
//                Log.e(TAG, "hasOffLine");
                SparseIntArray nodeArray = new SparseIntArray();
                for (int i = 0; i < intArray.size(); i++) {
                    int index = intArray.get(i);
                    for (int j = 0; j < Constant.BitMask0.length; j++) {
                        if ((frameByte[index] & Constant.BitMask0[j]) > 0) {
                            nodeArray.put(nodeArray.size(), (index * 8) + j);
                        }
                    }
                }
                EventBus.getDefault().post(new NodeOffLineEvent(portId, true, nodeArray));
                holderOffLineClean = false;
            } else {
                if (!holderOffLineClean) {
                    holderOffLineClean = true;
                    EventBus.getDefault().post(new NodeOffLineEvent(portId, false));
                }
            }
        }
    }

    private int setTempThanReturnHolderId(int temp, int holderIndex) {
        if (holderIndex > 0) {
            HolderBean holderBean = DataUtil.holderList.get(holderIndex);
            holderBean.setTemperature(temp);
            return holderBean.getHolderId();
        }
        return -1;
    }

    private void sendTemp(int temp, int holderId) {
        HolderBean holderBean = DataUtil.holderSparseArray.get(holderId);
        if (holderBean != null) {
            List<String> stringList = new ArrayList<>();
            List<CapacitorBean> capacitorBeanList = holderBean.capacitorList;
            for (int i = 1, size = capacitorBeanList.size(); i < size; i++) {
                CapacitorBean capacitorBean = capacitorBeanList.get(i);
                if (!capacitorBean.isEmpty()) {
                    stringList.add(capacitorBean.getUid());
                }
            }
            if (stringList.size() > 0) {
                OvenTemperatureBatchData data = new OvenTemperatureBatchData(temp, stringList);
                OvenTemperatureBatchJsonObj jsonObj = new OvenTemperatureBatchJsonObj("",
                        (int) (System.currentTimeMillis() / 1000), data);
//                Log.e(TAG, "发送温度数据");
                //EventBus.getDefault().post(new SendJsonObjEvent(jsonObj));//注销温度数据上报
            }
        }
    }


    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        //将收集的一包完整的数据转发给服务器
        if (uviBeanList.size() > 0) {
            final List<UVIBean> uviList = uviBeanList;
            uviBeanList = new ArrayList<>();
            final List<IVData> ivDataList = new ArrayList<>();
            for (UVIBean uviBean : uviList) {
                ivDataList.add(new IVData(uviBean.getUid(), uviBean.getI(), uviBean.getV()));
            }
            IVBatchJsonObj jsonObj = new IVBatchJsonObj("", System.currentTimeMillis(), ivDataList);
            EventBus.getDefault().post(new SendJsonObjEvent(jsonObj));
        }
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        ByteBuf byteBuf = (ByteBuf) evt;
        ChannelFuture channelFuture = ctx.writeAndFlush(byteBuf);
        channelFuture.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
                if (future.isSuccess()) {
                    Log.e(TAG, "writeBytes success" + portId);
                } else {
                    Log.e(TAG, "writeBytes failed " + future.cause());
                }
            }
        });
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        //数据读取异常
        //将异常通知到UI界面
        EventBus.getDefault().post(new ConnectStateChangeEvent(portId, true));
        Log.e(TAG, "exceptionCaught cause " + cause.getMessage());
        ctx.close();
    }

    //链路编号=（机号-1）*3+端口-1
    //计算到链路编号，用链路编号去表中索引夹具的队列号
    private int getHolderIndex(int machineId, int portNumber) {
        return Constant.HolderPosTable[portId][(machineId - 1) * 3 + portNumber - 1];
    }

    private StringBuilder getHexDatas(byte[] bytes) {
        StringBuilder sb = new StringBuilder(30);
        for (int i = 0; i < bytes.length; i++) {
            if (i != 0 && i % 13 == 0) {
                sb.append('\n');
            }
            sb.append(MethodUtil.intToHex(bytes[i] & 0xFF));
            sb.append(" ");
        }
        return sb;
    }
}
